package com.ics.atable.chat.service.impl;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ics.atable.chat.common.milvus.MilvusMultiVectorStore;
import com.ics.atable.chat.constant.VectorDatabaseConstant;
import com.ics.atable.chat.model.dto.ItemEmbeddingDTO;
import com.ics.atable.chat.model.dto.ItemImportDTO;
import com.ics.atable.chat.service.EmbeddingService;
import com.ics.atable.chat.service.ExcelService;
import com.ics.atable.chat.service.ItemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;

/**
 * 指标管理服务实现类
 *
 * @author Chawu
 */
@Slf4j
@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private ExcelService excelService;

    @Autowired
    private EmbeddingService embeddingService;

    @Autowired
    private MilvusMultiVectorStore milvusMultiVectorStore;

    @Override
    public List<ItemImportDTO> processExcelFile(MultipartFile file) throws Exception {
        log.info("开始处理Excel文件: {}, 大小: {} bytes", file.getOriginalFilename(), file.getSize());
        
        // 1. 验证文件
        validateExcelFile(file);
        
        // 2. 解析Excel文件
        List<ItemImportDTO> itemList = excelService.parseExcelFile(file);
        log.info("Excel文件解析完成，共解析出{}条数据", itemList.size());
        
        // 3. 向量化处理
        // 把每一个itemList中的item取出itemName，和itemFatherName进行向量化处理
        log.info("开始向量化数据...");
        List<ItemEmbeddingDTO> ItemEmbeddingDTOList = new ArrayList<>();
        int totalCount = itemList.size();
        int processedCount = 0;
        for (ItemImportDTO item : itemList) {
            ItemEmbeddingDTO embedding = new ItemEmbeddingDTO();
            // 等待向量化的数据
            List<String> messages = new ArrayList<>();
            messages.add(item.getItemFullName());
            messages.add(item.getItemName());
            messages.add(item.getItemFatherName());
            messages.add(item.getItemGrandfatherName());
            // 传入向量化服务
            EmbeddingResponse embeddingResponse = embeddingService.embedding(messages);
//            log.info("向量化结果: {}", embeddingResponse);
            embedding.setItemFullName(embeddingResponse.getResults().get(0).getOutput());
            embedding.setItemName(embeddingResponse.getResults().get(1).getOutput());
            embedding.setItemFatherName(embeddingResponse.getResults().get(2).getOutput());
            embedding.setItemGrandfatherName(embeddingResponse.getResults().get(3).getOutput());
            embedding.setItemUuid(item.getItemUuid());
            embedding.setMetadata(item.getMetadata());
            ItemEmbeddingDTOList.add(embedding);
//            log.info("向量化完成: {}", embedding);
            // 输出向量化进程
            processedCount++;
            if (processedCount % 50 == 0 || processedCount == totalCount) {
                int percent = (int) ((processedCount * 100L) / totalCount);
                log.info("向量化进度: {} / {} ({}%)", processedCount, totalCount, percent);
            }
        }
        log.info("向量化完成，共向量化出{}条数据", ItemEmbeddingDTOList.size());

        
        // 4. 存储到向量数据库
        // 调用milvusMultiVectorStore存储向量数据
        try {
            if (milvusMultiVectorStore.hasCollection(VectorDatabaseConstant.ITEM_COLLECTION_NAME)){
                log.info("集合已存在，开始加载集合: {}", VectorDatabaseConstant.ITEM_COLLECTION_NAME);
                milvusMultiVectorStore.loadCollection(VectorDatabaseConstant.ITEM_COLLECTION_NAME);
                // 准备数据
                List<JsonObject> milvusData = convertToMilvusDataFormat(ItemEmbeddingDTOList);
                // 然后可以将milvusData存储到Milvus数据库中
                milvusMultiVectorStore.insert(milvusData, VectorDatabaseConstant.ITEM_COLLECTION_NAME);
                log.info("数据存储完成");
            }else{
                log.info("集合不存在，开始创建集合（未实现）: {}", VectorDatabaseConstant.ITEM_COLLECTION_NAME);
                // TODO 集合不存在需要新建
            }
        } catch (Exception e) {
            log.error("导入数据失败: {}", VectorDatabaseConstant.ITEM_COLLECTION_NAME, e);
        }finally {
            milvusMultiVectorStore.releaseCollection(VectorDatabaseConstant.ITEM_COLLECTION_NAME);
            log.info("释放集合完成: {}", VectorDatabaseConstant.ITEM_COLLECTION_NAME);
        }

        log.info("数据导入完成");
        return itemList;
    }

    @Override
    public void validateExcelFile(MultipartFile file) throws IllegalArgumentException {
        // 验证文件是否为空
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }
        
        // 验证文件格式
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".xlsx")) {
            throw new IllegalArgumentException("只支持.xlsx格式的Excel文件");
        }
        
        // 验证文件大小（限制为10MB）
        if (file.getSize() > 10 * 1024 * 1024) {
            throw new IllegalArgumentException("文件大小不能超过10MB");
        }
        
        log.info("文件验证通过: {}", originalFilename);
    }

    @Override
    public List<JsonObject> convertToMilvusDataFormat(List<ItemEmbeddingDTO> embeddingList) {
        Gson gson = new Gson();
        List<JsonObject> milvusDataList = new ArrayList<>();

        for (ItemEmbeddingDTO item : embeddingList) {
            JsonObject jsonObject = new JsonObject();
            jsonObject.addProperty("item_uuid", item.getItemUuid());
            jsonObject.add("item_full_name", gson.toJsonTree(item.getItemFullName()));
            jsonObject.add("item_name", gson.toJsonTree(item.getItemName()));
            jsonObject.add("item_father_name", gson.toJsonTree(item.getItemFatherName()));
            jsonObject.add("item_grandfather_name", gson.toJsonTree(item.getItemGrandfatherName()));

            // 添加metadata
            if (item.getMetadata() != null) {
                jsonObject.addProperty("metadata", item.getMetadata());
            }

            milvusDataList.add(jsonObject);
        }

        return milvusDataList;
    }
}
